package dao;

import java.beans.XMLDecoder;
import java.beans.XMLEncoder;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;


/**
 * Class responsible for the operations of Announcement
 */ 
public abstract class AbstractDAO<T extends IDIF> implements DAO<T> {

	/**
	 * Lists announcement
	 * @see dao.DAO#list()
	 */	
	@SuppressWarnings("unchecked")
	public List<T> list() {
		XMLDecoder decoder = null;
		List<T> list;
		try {
			decoder = new XMLDecoder(new BufferedInputStream(
					new FileInputStream(getDBFileName())));
			list = (List<T>) decoder.readObject();
			return list;
		} catch (Exception e1) {
			return new ArrayList<T>();
		} finally {
			if (decoder != null) {
				decoder.close();
			}
		}
	}

	/**
	 * Delete a T bean from DB
	 * @param bean - bean will be deleted
	 * @return true, bean deleted
	 *         false, bean not deleted
	 * @see dao.DAO#delete(dao.T)
	 */
	public boolean delete(T bean) {
		List<T> blogs = list();
		Iterator<T> it = blogs.iterator();
		T savedBean;
		while (it.hasNext()) {
			savedBean = it.next();
			if (bean.getId().equals(savedBean.getId())) {
				blogs.remove(savedBean);
				return writeList(blogs);
			}

		}
		return false;
	}


	/**
	 * Update a T bean to DB
	 * @param bean - bean to be update
	 * @return true if bean was updated false otherwise.
	 * @see dao.DAO#update(dao.T)
	 */
	public boolean update(T bean) {
		List<T> blogs = list();
		Iterator<T> it = blogs.iterator();
		T post;
		while (it.hasNext()) {
			post = it.next();
			if (bean.getId().equals(post.getId())) {
				blogs.remove(post);
				blogs.add(bean);
				return writeList(blogs);
			}

		}
		return false;
	}


	/**
	 * Save a T bean to DB
	 * @param bean - bean will be save
	 * @return true, bean save
	 *         false, bean not save
	 * @see dao.DAO#save(dao.T)
	 */
	public boolean save(T bean) {
		List<T> list = list();
		list.add(bean);
		return writeList(list);
	}

	/**
	 * Check if DB contains the given bean
	 * @param bean - bean will be check
	 * @return true, bean is contained
	 *         false, bean is not contained
	 * @see dao.DAO#contains(dao.T)
	 */
	public boolean contains(T bean) {
		List<T> blogs = list();
		Iterator<T> it = blogs.iterator();
		T post;
		while (it.hasNext()) {
			post = it.next();
			if (bean.equals(post)) {
				return true;

			}

		}
		return false;
	}

	/**
	 * Write list
	 * @param list - list will be write
	 * @return true, list was write
	 *         false, list was not write
	 */
	private boolean writeList(List<T> list) {
		XMLEncoder encoder = null;
		try {
			encoder = new XMLEncoder(new BufferedOutputStream(
					new FileOutputStream(getDBFileName())));
			encoder.writeObject(list);
			return true;
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} finally {
			if (encoder != null) {
				encoder.close();
			}
		}
		return false;
	}

	/**
	 * Factory method
	 * @return
	 */
	protected abstract File getDBFileName();

}

